using AutoMapper;
using B.S.Data.MES.API.Applications.CangKu.Command;
using B.S.Domain.CangKu;
using B.S.Infratrctrue;
using B.S.Requst;
using MediatR;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System;
using Microsoft.EntityFrameworkCore;

namespace B.S.Data.MES.API.Applications.CangKu.CommandHandlers
{
    public class AddShangpininfoCommandHandler : IRequestHandler<FenPeiCommand, APIRequst<int>>
    {
        private readonly IBaseRepository<RuKuinfo> ruKuRepository;
        private readonly IBaseRepository<CangKuinfo> cangKuRepository;
        private readonly IBaseRepository<CangKuQU> kuquRepository;
        private readonly IBaseRepository<ChuWei> chuWeiRepository;
        private readonly IBaseRepository<Finished_ProductTest> findRepository;
        private readonly IBaseRepository<RukuinfoLog> rukuLogRepository;

        public AddShangpininfoCommandHandler(
            IBaseRepository<RuKuinfo> ruKuRepository,
            IMapper mapper,
            IBaseRepository<CangKuinfo> cangKuRepository,
            IBaseRepository<CangKuQU> KuquRepository,
            IBaseRepository<ChuWei> ChuWeiRepository,
            IBaseRepository<Finished_ProductTest> findRepository,
            IBaseRepository<RukuinfoLog> rukuLogRepository)
        {
            this.ruKuRepository = ruKuRepository;
            this.cangKuRepository = cangKuRepository;
            this.kuquRepository = KuquRepository;
            this.chuWeiRepository = ChuWeiRepository;
            this.findRepository = findRepository;
            this.rukuLogRepository = rukuLogRepository;
        }

        public async Task<APIRequst<int>> Handle(FenPeiCommand request, CancellationToken cancellationToken)
        {
            // 1. 校验Code
            if (string.IsNullOrWhiteSpace(request.Code))
                return new APIRequst<int> { Code = RequstCode.失败, Msg = "请求编码为空" };

            // 为了保证事务内一致性，使用 ruKuRepository.db 的 DbContext 来查询并更新
            var db = ruKuRepository.db;

            // 2. 检验表查找（在同一 DbContext 中查询）
            var product = await db.Set<Finished_ProductTest>().FirstOrDefaultAsync(p => p.SID == request.Code, cancellationToken);
            if (product == null)
                return new APIRequst<int> { Code = RequstCode.失败, Msg = "未在检验表中找到该编码的记录，无法入库" };

            // 3. 校验检验表中数量是否足够
            if (product.ProductCount < request.Count)
                return new APIRequst<int> { Code = RequstCode.失败, Msg = "数量不足，无法入库" };

            // 4. 检查是否已存在入库记录（支持分批次入库）
            var existingRukuInfo = await db.Set<RuKuinfo>().FirstOrDefaultAsync(f => f.SID == product.SID, cancellationToken);

            using var transaction = await db.Database.BeginTransactionAsync(cancellationToken);
            try
            {
                if (existingRukuInfo != null)
                {
                    // 4.1 如果已存在入库记录，则更新数量（分批次入库）
                    existingRukuInfo.ProductCount += request.Count;
                    db.Set<RuKuinfo>().Update(existingRukuInfo);
                }
                else
                {
                    // 4.2 如果不存在入库记录，则创建新记录（首次入库）
                    // 根据 State 决定目标仓库
                    int cangId = 0;
                    if (request.State == 1)
                        cangId = await db.Set<CangKuinfo>().Where(x => x.CangName == "成品仓库").Select(x => x.CangId).FirstOrDefaultAsync(cancellationToken);
                    else if (request.State == 2)
                        cangId = await db.Set<CangKuinfo>().Where(x => x.CangName == "半成品仓库").Select(x => x.CangId).FirstOrDefaultAsync(cancellationToken);
                    else if (request.State == 3)
                        cangId = await db.Set<CangKuinfo>().Where(x => x.CangName == "残次品仓库").Select(x => x.CangId).FirstOrDefaultAsync(cancellationToken);

                    if (cangId == 0)
                        return new APIRequst<int> { Code = RequstCode.失败, Msg = "未找到目标仓库" };

                    // 查库位
                    var cangInfo = await db.Set<CangKuinfo>().FirstOrDefaultAsync(x => x.CangId == cangId, cancellationToken);
                    if (cangInfo == null || string.IsNullOrWhiteSpace(cangInfo.CangkuNo))
                        return new APIRequst<int> { Code = RequstCode.失败, Msg = "仓库信息不完整或未配置仓库编号（CangkuNo）" };

                    var kuquList = await db.Set<CangKuQU>().Where(x => x.BM == cangInfo.CangkuNo).ToListAsync(cancellationToken);
                    if (kuquList == null || !kuquList.Any())
                        return new APIRequst<int> { Code = RequstCode.失败, Msg = "该仓库下没有库位" };

                    var selectedKu = kuquList.First();

                    // 查储位
                    var kuweiIds = kuquList.Select(k => k.CangKuId).ToList();
                    var chuweiList = await db.Set<ChuWei>().Where(x => kuweiIds.Contains(x.KuWeiId)).ToListAsync(cancellationToken);
                    if (chuweiList == null || !chuweiList.Any())
                        return new APIRequst<int> { Code = RequstCode.失败, Msg = "该仓库下没有储位" };

                    var takenChuIds = await db.Set<RuKuinfo>().Select(f => f.ChuId).ToListAsync(cancellationToken);
                    var freeChu = chuweiList.FirstOrDefault(c => !takenChuIds.Contains(c.ChuId));
                    if (freeChu == null)
                        return new APIRequst<int> { Code = RequstCode.失败, Msg = "没有可用的储位可分配" };

                    // 创建新的入库记录
                    var newRuku = new RuKuinfo
                    {
                        CangId = cangId,
                        CangKuId = selectedKu.CangKuId,
                        ChuId = freeChu.ChuId,
                        SID = product.SID,
                        ProductName = product.ProductName,
                        ProductStandard = product.ProductStandard,
                        ProductCount = request.Count,
                        ProductColor = product.ProductColor,
                        ProductState = product.ProductState,
                        RKState = "已入库",
                    };

                    db.Set<RuKuinfo>().Add(newRuku);
                }

                // 5. 创建入库日志（无论是新增还是更新都记录日志）
                var log = new RukuinfoLog
                {
                    RukuName = $"入库-{product.SID}",
                    Date = DateTime.Now,
                };
                db.Set<RukuinfoLog>().Add(log);

                // 6. 更新检验表数量
                product.ProductCount -= request.Count;
                // 当数量为 0 时更新状态字段
                if (product.ProductCount <= 0)
                {
                    product.ProductCount = 0;
                    product.RKState = "已入库";
                }

                db.Set<Finished_ProductTest>().Update(product);

                await db.SaveChangesAsync(cancellationToken);
                await transaction.CommitAsync(cancellationToken);

                return new APIRequst<int> { Code = RequstCode.成功, Msg = existingRukuInfo != null ? "分批次入库成功" : "首次入库成功" };
            }
            catch (Exception ex)
            {
                try
                {
                    await transaction.RollbackAsync(cancellationToken);
                }
                catch { /* ignore rollback errors */ }

                return new APIRequst<int> { Code = RequstCode.失败, Msg = $"入库失败：{ex.Message}" };
            }
        }
    }
}
